<template>
  <div class="awl">
    <div ref="vtkContainer" />
    <table class="controls">
      <tbody>
        <tr>
          <td>TipResolution</td>
          <td colspan="3">
            <input
              class="tipResolution"
              type="range"
              min="4"
              max="100"
              step="1"
              :value="coneResolution"
              @change="setResolution($event.target.value)"
            />
          </td>
        </tr>
        <tr>
          <td>TipRadius</td>
          <td colspan="3">
            <input class="tipRadius" type="range" min="0.01" max="1.0" step="0.01" value="0.1" @change="setRadius($event.target.value)" />
          </td>
        </tr>
        <tr>
          <td>TipLength</td>
          <td colspan="3">
            <input class="tipLength" type="range" min="0.1" max="0.5" step="0.05" value="0.35" @change="setLength($event.target.value)" />
          </td>
        </tr>
        <tr>
          <td>ShaftResolution</td>
          <td colspan="3">
            <input class="shaftResolution" type="range" min="4" max="100" step="1" value="6" @change="setShaftResolution($event.target.value)" />
          </td>
        </tr>
        <tr>
          <td>ShaftRadius</td>
          <td colspan="3">
            <input class="shaftRadius" type="range" min="0.01" max="1.0" step="0.01" value="0.03" @change="setShaftRadius($event.target.value)" />
          </td>
        </tr>
        <tr>
          <td>Invert</td>
          <td colspan="3"><input class="invert" type="checkbox" :checked="invert" @change="changeInvert($event.target.checked)" /></td>
        </tr>
        <tr style="text-align: center">
          <td></td>
          <td>X</td>
          <td>Y</td>
          <td>Z</td>
        </tr>
        <tr>
          <td>Direction</td>
          <td>
            <input
              style="width: 50px"
              class="direction"
              data-index="0"
              type="range"
              min="-1"
              max="1"
              step="0.1"
              value="1"
              @input="changeOx($event.target.value)"
            />
          </td>
          <td>
            <input
              style="width: 50px"
              class="direction"
              data-index="1"
              type="range"
              min="-1"
              max="1"
              step="0.1"
              value="0"
              @input="changeOy($event.target.value)"
            />
          </td>
          <td>
            <input
              style="width: 50px"
              class="direction"
              data-index="2"
              type="range"
              min="-1"
              max="1"
              step="0.1"
              value="0"
              @input="changeOz($event.target.value)"
            />
          </td>
        </tr>
        <tr>
          <td><input class="reset" type="button" value="Reset" @click="setReset" /></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script setup>
import { ref, unref, onMounted, onBeforeUnmount, watchEffect } from 'vue'

import '@kitware/vtk.js/Rendering/Profiles/Geometry'

import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow'

import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor'
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper'
import vtkArrowSource from '@kitware/vtk.js/Filters/Sources/ArrowSource'

const vtkContainer = ref(null)
const context = ref(null)

const length = ref(0.35)
const coneResolution = ref(6)
const radius = ref(0.1)
const shaftResolution = ref(6)
const shaftRadius = ref(0.03)
const invert = ref(false)
const oX = ref(1)
const oY = ref(0)
const oZ = ref(0)
function setResolution(rep) {
  coneResolution.value = Number(rep)
}
function setRadius(val) {
  radius.value = Number(val)
}
function setLength(val) {
  length.value = Number(val)
}
function setShaftResolution(val) {
  shaftResolution.value = Number(val)
}
function setShaftRadius(val) {
  shaftRadius.value = Number(val)
}
function changeInvert(val) {
  invert.value = val
}
function changeOx(x) {
  oX.value = Number(x)
}
function changeOy(y) {
  oY.value = Number(y)
}
function changeOz(z) {
  oZ.value = Number(z)
}
function setReset() {
  length.value = 0.35
  coneResolution.value = 6
  radius.value = 0.1
  shaftResolution.value = 6
  shaftRadius.value = 0.03
  invert.value = false
  oX.value = 1
  oY.value = 0
  oZ.value = 0
}

watchEffect(() => {
  const res = unref(coneResolution)
  const ra = unref(radius)
  const le = unref(length)
  const re = unref(shaftResolution)
  const rd = unref(shaftRadius)
  const bol = unref(invert)
  const ox = unref(oX)
  const oy = unref(oY)
  const oz = unref(oZ)
  if (context.value) {
    const { actor, coneSource, renderWindow } = context.value
    coneSource.setTipResolution(res)
    coneSource.setTipRadius(ra)
    coneSource.setTipLength(le)
    coneSource.setShaftResolution(re)
    coneSource.setShaftRadius(rd)
    coneSource.setInvert(bol)
    coneSource.setDirection(ox, oy, oz)
    actor.getProperty()
    renderWindow.render()
  }
})

onMounted(() => {
  if (!context.value) {
    const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
      rootContainer: vtkContainer.value
    })
    const coneSource = vtkArrowSource.newInstance()

    const mapper = vtkMapper.newInstance()
    mapper.setInputConnection(coneSource.getOutputPort())

    const actor = vtkActor.newInstance()
    actor.setMapper(mapper)

    const renderer = fullScreenRenderer.getRenderer()
    const renderWindow = fullScreenRenderer.getRenderWindow()

    renderer.addActor(actor)
    renderer.resetCamera()
    renderWindow.render()

    context.value = {
      fullScreenRenderer,
      renderWindow,
      renderer,
      coneSource,
      actor,
      mapper
    }
  }
})

onBeforeUnmount(() => {
  if (context.value) {
    const { fullScreenRenderer, coneSource, actor, mapper } = context.value
    actor.delete()
    mapper.delete()
    coneSource.delete()
    fullScreenRenderer.delete()
    context.value = null
  }
})
</script>
<style lang="scss" scoped>
.awl {
  margin: 0px;
  padding: 0px;
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  overflow: hidden;
  cursor: pointer;
  touch-action: none;
  user-select: none;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.controls {
  position: absolute;
  left: 25px;
  top: 25px;
  background-color: white;
  border-radius: 5px;
  list-style: none;
  padding: 5px 10px;
  margin: 0px;
  display: block;
  border: 1px solid black;
  max-width: calc(100% - 70px);
  max-height: calc(100% - 60px);
  overflow: auto;
}
</style>
